{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/bitkira/Colab/blob/main/tutorial_notebooks/first_workflow.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "!pip install git+https://github.com/EvoAgentX/EvoAgentX.git"
      ],
      "metadata": {
        "id": "rJF2QTYsdoC5"
      },
      "id": "rJF2QTYsdoC5",
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!pip install PyPDF2 selenium html2text fastmcp"
      ],
      "metadata": {
        "id": "ZGN1cTpedoVH"
      },
      "id": "ZGN1cTpedoVH",
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "id": "dee0a2b5",
      "metadata": {
        "id": "dee0a2b5"
      },
      "source": [
        "# Build Your First Workflow\n",
        "\n",
        "In EvoAgentX, workflows allow multiple agents to collaborate sequentially on complex tasks. This tutorial will guide you through creating and using workflows:\n",
        "\n",
        "1. **Understanding Sequential Workflows**: Learn how workflows connect multiple tasks together\n",
        "2. **Building a Sequential Workflow**: Create a workflow with planning and coding steps\n",
        "3. **Executing and Managing Workflows**: Run workflows with specific inputs\n",
        "\n",
        "By the end of this tutorial, you'll be able to create sequential workflows that coordinate multiple agents to solve complex problems.\n",
        "\n",
        "## 1. Understanding Sequential Workflows\n",
        "\n",
        "A workflow in EvoAgentX represents a sequence of tasks that can be executed by different agents. The simplest workflow is a sequential workflow, where tasks are executed one after another with outputs from previous tasks feeding into subsequent ones.\n",
        "\n",
        "Let's start by importing the necessary components:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "212e296e",
      "metadata": {
        "id": "212e296e"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "from dotenv import load_dotenv\n",
        "from evoagentx.workflow import SequentialWorkFlowGraph, WorkFlow\n",
        "from evoagentx.agents import AgentManager\n",
        "from evoagentx.models import OpenAILLMConfig, OpenAILLM\n",
        "\n",
        "try:\n",
        "    from google.colab import userdata\n",
        "    OPENAI_API_KEY = userdata.get(\"OPENAI_API_KEY\")\n",
        "except ImportError:\n",
        "    OPENAI_API_KEY = None\n",
        "\n",
        "if not OPENAI_API_KEY:\n",
        "    load_dotenv()\n",
        "    OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a1f208d7",
      "metadata": {
        "id": "a1f208d7"
      },
      "source": [
        "\n",
        "## 2. Building a Sequential Workflow\n",
        "\n",
        "A sequential workflow consists of a series of tasks where each task has:\n",
        "\n",
        "- A name and description\n",
        "- Input and output definitions\n",
        "- A prompt template\n",
        "- Parsing mode and function (optional)\n",
        "\n",
        "Here's how to build a sequential workflow with planning and coding tasks:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f6947ac7",
      "metadata": {
        "id": "f6947ac7"
      },
      "outputs": [],
      "source": [
        "# Configure the LLM\n",
        "llm_config = OpenAILLMConfig(model=\"gpt-4o-mini\", openai_key=OPENAI_API_KEY, stream=True, output_response=True)\n",
        "llm = OpenAILLM(llm_config)\n",
        "\n",
        "# Define a custom parsing function (if needed)\n",
        "from evoagentx.core.registry import register_parse_function\n",
        "from evoagentx.core.module_utils import extract_code_blocks\n",
        "\n",
        "# [optional] Define a custom parsing function (if needed)\n",
        "# It is suggested to use the `@register_parse_function` decorator to register a custom parsing function, so the workflow can be saved and loaded correctly.\n",
        "\n",
        "@register_parse_function\n",
        "def custom_parse_func(content: str) -> str:\n",
        "    return {\"code\": extract_code_blocks(content)[0]}\n",
        "\n",
        "# Define sequential tasks\n",
        "tasks = [\n",
        "    {\n",
        "        \"name\": \"Planning\",\n",
        "        \"description\": \"Create a detailed plan for code generation\",\n",
        "        \"inputs\": [\n",
        "            {\"name\": \"problem\", \"type\": \"str\", \"required\": True, \"description\": \"Description of the problem to be solved\"},\n",
        "        ],\n",
        "        \"outputs\": [\n",
        "            {\"name\": \"plan\", \"type\": \"str\", \"required\": True, \"description\": \"Detailed plan with steps, components, and architecture\"}\n",
        "        ],\n",
        "        \"prompt\": \"You are a software architect. Your task is to create a detailed implementation plan for the given problem.\\n\\nProblem: {problem}\\n\\nPlease provide a comprehensive implementation plan including:\\n1. Problem breakdown\\n2. Algorithm or approach selection\\n3. Implementation steps\\n4. Potential edge cases and solutions\",\n",
        "        \"parse_mode\": \"str\",\n",
        "        # \"llm_config\": specific_llm_config # if you want to use a specific LLM for a task, you can add a key `llm_config` in the task dict.\n",
        "    },\n",
        "    {\n",
        "        \"name\": \"Coding\",\n",
        "        \"description\": \"Implement the code based on the implementation plan\",\n",
        "        \"inputs\": [\n",
        "            {\"name\": \"problem\", \"type\": \"str\", \"required\": True, \"description\": \"Description of the problem to be solved\"},\n",
        "            {\"name\": \"plan\", \"type\": \"str\", \"required\": True, \"description\": \"Detailed implementation plan from the Planning phase\"},\n",
        "        ],\n",
        "        \"outputs\": [\n",
        "            {\"name\": \"code\", \"type\": \"str\", \"required\": True, \"description\": \"Implemented code with explanations\"}\n",
        "        ],\n",
        "        \"prompt\": \"You are a software developer. Your task is to implement the code based on the provided problem and implementation plan.\\n\\nProblem: {problem}\\nImplementation Plan: {plan}\\n\\nPlease provide the implementation code with appropriate comments.\",\n",
        "        \"parse_mode\": \"custom\",\n",
        "        \"parse_func\": custom_parse_func\n",
        "    }\n",
        "]\n",
        "\n",
        "# Create the sequential workflow graph\n",
        "graph = SequentialWorkFlowGraph(\n",
        "    goal=\"Generate code to solve programming problems\",\n",
        "    tasks=tasks\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "af69c006",
      "metadata": {
        "id": "af69c006"
      },
      "source": [
        "> **Note**\n",
        ">\n",
        "> When you create a `SequentialWorkFlowGraph` with a list of tasks, the framework will create a `CustomizeAgent` for each task. Each task in the workflow becomes a specialized agent configured with the specific prompt, input/output formats, and parsing mode you defined. These agents are connected in sequence, with outputs from one agent becoming inputs to the next.\n",
        ">\n",
        "> The `parse_mode` controls how the output from an LLM is parsed into a structured format. Available options are: [`'str'` (default), `'json'`, `'title'`, `'xml'`, `'custom'`]. For detailed information about parsing modes and examples, please refer to the [CustomizeAgent documentation](../modules/customize_agent.md#parsing-modes).\n",
        "\n",
        "## 3. Executing and Managing Workflows\n",
        "\n",
        "Once you've created a workflow graph, you can create an instance of the workflow and execute it:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fcc95765",
      "metadata": {
        "id": "fcc95765"
      },
      "outputs": [],
      "source": [
        "import nest_asyncio\n",
        "nest_asyncio.apply()\n",
        "\n",
        "# Create agent manager and add agents from the workflow. It will create a `CustomizeAgent` for each task in the workflow.\n",
        "agent_manager = AgentManager()\n",
        "agent_manager.add_agents_from_workflow(\n",
        "    graph,\n",
        "    llm_config=llm_config  # This config will be used for all tasks without `llm_config`.\n",
        ")\n",
        "\n",
        "# Create workflow instance\n",
        "workflow = WorkFlow(graph=graph, agent_manager=agent_manager, llm=llm)\n",
        "\n",
        "# Execute the workflow with inputs\n",
        "output = workflow.execute(\n",
        "    inputs = {\n",
        "        \"problem\": \"Write a function to find the longest palindromic substring in a given string.\"\n",
        "    }\n",
        ")\n",
        "\n",
        "print(\"Workflow completed!\")\n",
        "print(\"Workflow output:\\n\", output)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "55a4e715",
      "metadata": {
        "id": "55a4e715"
      },
      "source": [
        "\n",
        "You should specify all the required inputs for the workflow in the `inputs` argument of the `execute` method.\n",
        "\n",
        "For a complete working example, please refer to the [Sequential Workflow example](https://github.com/EvoAgentX/EvoAgentX/blob/main/examples/sequential_workflow.py).\n",
        "\n",
        "## 4. Saving and Loading Workflows\n",
        "\n",
        "You can save a workflow graph for future use:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "7cf12e47",
      "metadata": {
        "id": "7cf12e47"
      },
      "outputs": [],
      "source": [
        "# Save the workflow graph to a file\n",
        "graph.save_module(\"examples/output/saved_sequential_workflow.json\")\n",
        "\n",
        "# Load the workflow graph from a file\n",
        "loaded_graph = SequentialWorkFlowGraph.from_file(\"examples/output/saved_sequential_workflow.json\")\n",
        "\n",
        "# Create a new workflow with the loaded graph\n",
        "new_workflow = WorkFlow(graph=loaded_graph, agent_manager=agent_manager, llm=llm)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cc81228d",
      "metadata": {
        "id": "cc81228d"
      },
      "source": [
        "\n",
        "For more complex workflows or different types of workflow graphs, please refer to the [Workflow Graphs](../modules/workflow_graph.md) documentation and the [Action Graphs](../modules/action_graph.md) documentation."
      ]
    }
  ],
  "metadata": {
    "language_info": {
      "name": "python"
    },
    "colab": {
      "provenance": [],
      "include_colab_link": true
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}